package net.csdn.business.auth.authing;

import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.oauth2.component.AuthingAuthenticationToken;
import net.csdn.business.common.utils.AuthUtil;
import net.csdn.business.auth.constant.SecurityConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Desc: authing登录验证filter
 * @ClassName: AuthingAuthenticationFilter
 * @Author: yourleige@163.com
 * @Date: 2022/9/26 15:40
 */
@Slf4j
public class AuthingAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

	private static final String SPRING_SECURITY_FORM_AUTHING_KEY = "aToken";

	@Getter
	@Setter
	private String authingParameter = SPRING_SECURITY_FORM_AUTHING_KEY;

	@Getter
	@Setter
	private boolean postOnly = true;

	@Getter
	@Setter
	private AuthenticationEntryPoint authenticationEntryPoint;

	public AuthingAuthenticationFilter() {
		super(new AntPathRequestMatcher(SecurityConstants.AUTHING_TOKEN_URL, "GET"));
	}

	@Override
	@SneakyThrows
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
		/*if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}*/
		//从cookie获取token
		String authingToken=AuthUtil.getIdToken(request);
		if(StringUtils.isBlank(authingToken)){
			authingToken = obtainAuthingToken(request);
		}
		log.info("----authingToken：{}--------",authingToken);
		if (authingToken != null) {
			authingToken = authingToken.trim();
		}
		AuthingAuthenticationToken authingAuthenticationToken = new AuthingAuthenticationToken(authingToken);
		setDetails(request, authingAuthenticationToken);
		Authentication authResult = null;
		try {
			authResult = this.getAuthenticationManager().authenticate(authingAuthenticationToken);
			log.debug("Authentication success: " + authResult);
			SecurityContextHolder.getContext().setAuthentication(authResult);
		}
		catch (Exception failed) {
			SecurityContextHolder.clearContext();
			log.debug("Authentication request failed: " + failed);
			try {
				authenticationEntryPoint.commence(request, response,
						new UsernameNotFoundException(failed.getMessage(), failed));
			}
			catch (Exception e) {
				log.error("authenticationEntryPoint handle error:{}", failed);
			}
		}
		return authResult;
	}

	private String obtainAuthingToken(HttpServletRequest request) {
		return request.getParameter(authingParameter);
	}

	private void setDetails(HttpServletRequest request, AuthingAuthenticationToken authRequest) {
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}

}
